package record;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;



/**
 * A class that represents a directory of projects for a user.
 * @author Stephan Jossie
 * @author Jacob Freemyer
 *
 */
@SuppressWarnings("serial")
public class Directory implements Serializable
{
	/**
	 * List of directories
	 */
	private List<Directory> directories;
	
	/**
	 * List of projects
	 */
	private List<ProjectRecord> projects;
	
	/**
	 * Name of directory
	 */
	private String name;
	
	/**
	 * Path of directory
	 */
	private String path;
	
	/**
	 * Creates an instance of Directory with a given name.
	 * @param dirName
	 * 		The name of the directory.
	 */
	public Directory(String dirName)
	{
		this(dirName, "root\\");
	}
	
	/**
	 * Create a new directory
	 * @param dirName
	 * Name of the directory
	 * @param dirPath
	 * Location of the directory
	 */
	public Directory(String dirName, String dirPath)
	{
		name = dirName;
		path = dirPath;
		directories = new ArrayList<Directory>();
		projects = new ArrayList<ProjectRecord>();
	}
	
	
	/**
	 * Getter to get the Directories in the Directory
	 * @return
	 * 		A list of all the Directories in the Directory
	 */
	public List<Directory> getDirectories()
	{
		return directories;
	}
	
	/**
	 * Getter to get the ProjectRecords in the directory
	 * @return
	 * 		A list of all the Project Records in the directory.
	 */
	public List<ProjectRecord> getRecords()
	{
		return projects;
	}
	
	/**
	 * Adds a directory to list of Directories in this.
	 * @param dir
	 * 		The Directory to add to this Directory
	 * @return
	 * 		True - added
	 * 		False - not-added
	 */
	public boolean addDirectory(Directory dir)
	{
		return directories.add(dir);
	}
	
	/**
	 * Adds a Project Record to the list of Project records in this Directory.
	 * @param record
	 * 		The ProjectRecord to add to this directory.
	 * @return
	 * 		True - added
	 * 		False - not-added
	 */
	public boolean addProject(ProjectRecord record)
	{
		return projects.add(record);
	}
	
	/**
	 * Size of the Directory
	 * @return
	 * 		Number of projects and directories in this Directory
	 */
	public int countContents()
	{
		return directories.size() + projects.size();
	}
	
	/**
	 * Finds the index of the given Directory in this.
	 * @param dir
	 * 		The name of the Directory to find in this.
	 * @return
	 * 		The index of the given directory.
	 */
	public int indexOf(Directory dir)
	{
		return directories.indexOf(dir);
	}
	
	/**
	 * Finds the index of the given ProjectRecord in this directory.
	 * @param record
	 * 		the name of the ProjectRecord to find in this directory.
	 * @return
	 * 		The index of the given ProjectRecord.
	 */
	public int indexOf(ProjectRecord record)
	{
		return directories.size() + projects.indexOf(record);
	}
	
	/**
	 * Gets either a directory or a project record.
	 * @param index
	 * 		The index in which to get a directory or record at.
	 * @return
	 * 		A Directory or a Project Record based on where the index is in the Directory, if index is 
	 * 		less than the number of directories in this, then a Directory is returned otherwise it's a ProjectRecord.
	 */
	public Object get(int index)
	{
		// if it's requesting an index in the range of the directories
		if(index < directories.size())
			return directories.get(index); 
		
		// otherwise, it's requesting an index in the range of the records
		return projects.get(index - directories.size());
	}
	
	/**
	 * Attempts to recursively find the directory located at the path given.
	 * @param path
	 * Location to find directory
	 * @return <code>null</code> if the directory is not found, else it returns
	 * the directory requested.
	 */
	public Directory findDirectory(String path)
	{
		for(Directory dir : directories)
		{
			if(dir.name.equals(path))
				return dir;
			else
				findDirectory(path);
		}
		
		return null;
	}
	
	
	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
		return name;
	}


	/**
	 * Returns the name of the directory
	 * @return
	 * The name
	 */
	public String getName()
	{
		return name;
	}


	/**
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((directories == null) ? 0 : directories.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result
				+ ((projects == null) ? 0 : projects.hashCode());
		return result;
	}


	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Directory other = (Directory) obj;
		if (directories == null)
		{
			if (other.directories != null)
				return false;
		}
		else if (!directories.equals(other.directories))
			return false;
		if (name == null)
		{
			if (other.name != null)
				return false;
		}
		else if (!name.equals(other.name))
			return false;
		if (projects == null)
		{
			if (other.projects != null)
				return false;
		}
		else if (!projects.equals(other.projects))
			return false;
		return true;
	}


	/**
	 * Returns the path of directory
	 * @return
	 * The path
	 */
	public String getPath()
	{
		return path;
	}
}
